﻿// WebZHX.Infrastructure/Extensions/QueryableExtensions.cs
using System;
using System.Linq;
using System.Linq.Expressions;

namespace Infrastructure.Extensions
{
    /// <summary>
    /// 查询扩展方法
    /// </summary>
    public static class QueryableExtensions
    {
        /// <summary>
        /// 动态排序
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="query">查询</param>
        /// <param name="orderBy">排序字段</param>
        /// <param name="isAscending">是否升序</param>
        /// <returns>排序后的查询</returns>
        public static IQueryable<T> OrderByDynamic<T>(this IQueryable<T> query, string orderBy, bool isAscending = true)
        {
            var parameter = Expression.Parameter(typeof(T), "x");
            var property = Expression.Property(parameter, orderBy);
            var lambda = Expression.Lambda(property, parameter);

            var methodName = isAscending ? "OrderBy" : "OrderByDescending";
            var resultExpression = Expression.Call(
                typeof(Queryable),
                methodName,
                new[] { typeof(T), property.Type },
                query.Expression,
                Expression.Quote(lambda));

            return query.Provider.CreateQuery<T>(resultExpression);
        }

        /// <summary>
        /// 动态过滤
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="query">查询</param>
        /// <param name="field">字段名</param>
        /// <param name="operatorType">操作符</param>
        /// <param name="value">值</param>
        /// <returns>过滤后的查询</returns>
        public static IQueryable<T> WhereDynamic<T>(this IQueryable<T> query, string field, string operatorType, object value)
        {
            var parameter = Expression.Parameter(typeof(T), "x");
            var property = Expression.Property(parameter, field);
            //var constant = Expression.Constant(value);

            // 处理可空类型的比较
            Expression constant = CreateConstantExpression(property.Type, value);

            Expression body = operatorType.ToLower() switch
            {
                "=" => Expression.Equal(property, constant),
                ">" => Expression.GreaterThan(property, constant),
                "<" => Expression.LessThan(property, constant),
                ">=" => Expression.GreaterThanOrEqual(property, constant),
                "<=" => Expression.LessThanOrEqual(property, constant),
                "like" => Expression.Call(property, "Contains", Type.EmptyTypes, constant),
                _ => Expression.Equal(property, constant)
            };

            var lambda = Expression.Lambda<Func<T, bool>>(body, parameter);
            return query.Where(lambda);
        }
        /// <summary>
        /// 创建常量表达式，处理可空类型转换
        /// </summary>
        private static Expression CreateConstantExpression(Type propertyType, object value)
        {
            if (value == null)
                return Expression.Constant(value, propertyType);

            try
            {
                // 获取实际的目标类型（如果是可空类型，获取其基础类型）
                Type targetType = propertyType;
                if (propertyType.IsGenericType &&
                    propertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
                {
                    targetType = Nullable.GetUnderlyingType(propertyType) ?? propertyType;
                }

                // 如果值类型与目标类型不匹配，尝试转换
                if (value.GetType() != targetType)
                {
                    // 特殊处理字符串到日期的转换
                    if (value is string stringValue && targetType == typeof(DateTime))
                    {
                        if (DateTime.TryParse(stringValue, out DateTime dateValue))
                        {
                            value = dateValue;
                        }
                        else
                        {
                            throw new ArgumentException($"无法将字符串 '{stringValue}' 转换为日期时间");
                        }
                    }
                    else
                    {
                        // 尝试类型转换
                        value = Convert.ChangeType(value, targetType);
                    }
                }

                // 如果属性是可空类型，但值是非空类型，需要包装
                if (propertyType.IsGenericType &&
                    propertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
                {
                    Type underlyingType = Nullable.GetUnderlyingType(propertyType);
                    if (underlyingType != null && value.GetType() == underlyingType)
                    {
                        var nullableValue = Activator.CreateInstance(propertyType, value);
                        return Expression.Constant(nullableValue, propertyType);
                    }
                }

                return Expression.Constant(value, propertyType);
            }
            catch (Exception ex)
            {
                // 如果转换失败，记录错误并使用原始值
                System.Diagnostics.Debug.WriteLine($"类型转换失败: {ex.Message}");
                return Expression.Constant(value, propertyType);
            }
        }
    }
}